package middleware

import (
	"encoding/json"
	"fmt"
	"github.com/samber/lo"
	"net/http"
	"private-domain-overseas-service/pkg/result"
	"private-domain-overseas-service/pkg/status/bizadmin"
	"private-domain-overseas-service/pkg/xerr"
	"private-domain-overseas-service/tools/ent"
	"private-domain-overseas-service/tools/ent/adminrouter"
)

type CheckAndAuthButtonMiddleware struct {
	Orm *ent.Client
}

func NewCheckAndAuthButtonMiddleware(orm *ent.Client) *CheckAndAuthButtonMiddleware {
	return &CheckAndAuthButtonMiddleware{
		orm,
	}
}

func (m *CheckAndAuthButtonMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		// 拿到请求头,防止直接get报错 todo
		headerMap := r.Header
		// 取出请求头中的buttonKey
		buttonKey := headerMap.Get("X-Button-Key")

		// 为空，拦截
		if buttonKey == "" {
			result.HttpResult(r, w, nil, xerr.ErrCodeMsg(xerr.ServerAdminPermissionDenied, "缺少按钮权限"))
			return
		}

		// 如果前端没有传，直接放行
		if buttonKey == "pass" {
			next(w, r)
			return
		}

		// 取出上一个中间件设置的用户信息
		buttonIdsString, ok := r.Context().Value("bids").(string)
		// 如果没有按钮信息，则用户没有权限，返回
		if !ok || buttonIdsString == "" {
			result.HttpResult(r, w, nil, xerr.ErrCodeMsg(xerr.ServerAdminPermissionDenied, fmt.Sprintf("缺少按钮权限：%v", buttonKey)))
			return
		}

		// 解析用户按钮信息
		buttonIds := make([]int, 0)
		err := json.Unmarshal([]byte(buttonIdsString), &buttonIds)
		// 如果解析失败，则用户没有权限，返回
		if err != nil {
			result.HttpResult(r, w, nil, xerr.ErrCodeMsg(xerr.ServerAdminPermissionDenied, "缺少按钮权限"))
			return
		}

		// 查询用户拥有的按钮
		buttons, buttonErr := m.Orm.AdminRouter.Query().
			Where(adminrouter.IDIn(buttonIds...)).
			Where(adminrouter.IsDeleteEQ(bizadmin.NotDelete)).
			Where(adminrouter.AdminRouterMenuTypeEQ(bizadmin.TypeButton)).
			Where(adminrouter.AdminRouterStatusEQ(bizadmin.StatusEnabled)).
			All(r.Context())
		// 如果查询失败，则用户没有权限，返回
		if buttonErr != nil {
			result.HttpResult(r, w, nil, xerr.ErrCodeMsg(xerr.ServerAdminPermissionDenied, "按钮权限查询失败"))
			return
		}

		// 拿到按钮名称，要与前端对照
		buttonKeys := lo.Map(buttons, func(item *ent.AdminRouter, _ int) string {
			return item.AdminRouterRouteName
		})

		if !lo.Contains(buttonKeys, buttonKey) {
			result.HttpResult(r, w, nil, xerr.ErrCodeMsg(xerr.ServerAdminPermissionDenied, "缺少按钮权限"))
			return
		}
		next(w, r)
	}
}
